import { type MaybeRefOrGetter, isRef } from 'vue';
import { getHashParams, setHashParams } from './helpers';

type ToValue<T> = T extends MaybeRefOrGetter<infer V> ? V : T;

export function useSyncToHashParams<T extends Record<string, {
  value: MaybeRefOrGetter<any>;
  serialize?: (value: any) => string;
  parse?: (value: string) => any;
}>>(paramsConfig: T) {
  const initParams: Record<string, any> = {};

  for (const key in paramsConfig) {
    const param = paramsConfig[key];
    param.parse ??= value => value;
    const hashParams = getHashParams();
    const hashValue = hashParams.get(key);
    const useHashValue = hashValue !== null && hashValue !== 'undefined' && hashValue !== 'null' && hashValue !== '' && hashValue !== 'NaN';

    if (useHashValue) {
      if (isRef(param.value))
        param.value.value = param.parse(hashValue);
      else
        param.value = param.parse(hashValue);
    }

    initParams[key] = param.value;
  }

  const reactiveParams = reactive(initParams as { [K in keyof T]: ToValue<T[K]['value']> });

  watch(
    () => reactiveParams,
    (newVal: any) => {
      const hashParams = getHashParams();

      for (const key in newVal) {
        const { serialize = (value: any) => value } = paramsConfig[key];
        hashParams.set(key, serialize(newVal[key]));
      }

      setHashParams(hashParams, true);
    },
    { immediate: true, deep: true },
  );

  // 组件销毁时删除 URL 的 hash 参数
  onBeforeUnmount(() => {
    const hashParams = getHashParams();
    Object.keys(reactiveParams).forEach(key => hashParams.delete(key));
    setHashParams(hashParams, true);
  });

  return reactiveParams;
}
